org 0x7c00
[bits 16]
xor ax, ax ; eax = 0
; 初始化段寄存器, 段地址全部设为0
mov ds, ax
mov ss, ax
mov es, ax
mov fs, ax
mov gs, ax

; 初始化栈指针
mov sp, 0x7c00
mov ax, 1                ; 逻辑扇区号第0~15位
mov cx, 0                ; 逻辑扇区号第16~31位
mov bx, 0x7e00           ; bootloader的加载地址
load_bootloader:
    ;call asm_read_hard_disk  ; 读取硬盘
    call asm_read_hard_disk_chs ;chs 模式读取硬盘
    inc ax
    cmp ax, 5
    jle load_bootloader
jmp 0x0000:0x7e00        ; 跳转到bootloader
jmp $ ; 死循环

asm_read_hard_disk:                           
; 从硬盘读取一个逻辑扇区

; 参数列表
; ax=逻辑扇区号0~15位
; cx=逻辑扇区号16~28位
; ds:bx=读取出的数据放入地址

; 返回值
; bx=bx+512

    mov dx, 0x1f3
    out dx, al    ; LBA地址7~0

    inc dx        ; 0x1f4
    mov al, ah
    out dx, al    ; LBA地址15~8

    mov ax, cx

    inc dx        ; 0x1f5
    out dx, al    ; LBA地址23~16

    inc dx        ; 0x1f6
    mov al, ah
    and al, 0x0f
    or al, 0xe0   ; LBA地址27~24
    out dx, al

    mov dx, 0x1f2
    mov al, 1
    out dx, al   ; 读取1个扇区

    mov dx, 0x1f7    ; 0x1f7
    mov al, 0x20     ;读命令
    out dx,al

    ; 等待处理其他操作
  .waits:
    in al, dx        ; dx = 0x1f7
    and al,0x88
    cmp al,0x08
    jnz .waits                         
    

    ; 读取512字节到地址ds:bx
    mov cx, 256   ; 每次读取一个字，2个字节，因此读取256次即可          
    mov dx, 0x1f0
  .readw:
    in ax, dx
    mov [bx], ax
    add bx, 2
    loop .readw
      
    ret

asm_read_hard_disk_chs:
; chs model    al扇区数 ch柱面 cl扇区 dh磁头 dl驱动器  es:bx 缓冲区地址
; 驱动器号 80h 磁道扇区数 63 每柱面磁头(道)数 18
; lba=(cylinder*headPerCylinder18+head)*sectorPerTrack63+sector-1
; cylinder= lba/(sectorPerTrack63*headPerCylinder18)
; head=(lba/sectorPerTrack63)%headPerCylinder18
; sector=lba%sectorPerTrack63+1
; lba model 已知 cx:ax 为扇区 28 位编号，ds:bx 读取数据地址
; chs return result cf=0,ah=0,al 传输扇区数 否则 ah为状态代码
    call caculate
    mov ah,02h
    mov al,1
    mov dl,80h
    int 13h
    ret
caculate:
    push ebx
    push esi
    
    mov bx,cx
    shl ebx,16
    mov bx,ax	;lba
    mov ecx,0
    
    mov edx,0
    mov eax,ebx
    mov esi,63
    idiv esi
    mov cl,dl	;sector
    inc cx
    
    mov edx,0
    mov esi,18
    idiv esi
    mov dh,dl	;head
    mov ch,al	;cylinder
    
    pop esi
    pop ebx
    ret

times 510 - ($-$$) db 0
db 0x55,0xaa
